SECTION .data

SECTION .bss

SECTION .text

;extern void switch_asm(void *next_thread_registers,void **next_thread_stack,void *curr_thread_registers, void **curr_thread_stack);
;extern void load_registers_asm(void *new_thread_registers);

global switch_asm
global load_registers_asm
global save_context_asm
global restore_context_asm

;										ESP+4						ESP+8
; It accepts 2 parameters an void *curr_thread_registers, void **curr_thread_stack
save_context_asm:

	nop

	;store current stack pointer into active memory of current thread
	mov eax, DWORD [esp+8] ;esp+12 is the adress of the prev thread stack !
	mov [eax],esp	;store the old stack into memory


	push ebp
	mov ebp,esp

	;function arguments that were passed !
	;[ebp+4] is eip
	;[ebp+8] is the current thread's adress of registers
	;[ebp+12] is the adress current thread's active stack


	;save EIP
	mov eax,DWORD [ebp+8]
	push edx
	mov edx, DWORD [ebp+4]
	mov [eax],edx
	pop edx

	;save EBX
	mov [eax+4],ebx
	;save ESI
	mov [eax+8],esi
	;save EDI
	mov [eax+12],edi
	;save ECX
	mov [eax+16],ecx
	;save EDX
	mov [eax+20],edx
	;save EBP
	pop ebp
	mov [eax+24],ebp

	;save FS
	;xor	edx, edx
	;mov	dx,fs
	;mov	[eax+28],edx

	xor eax,eax

	nop
	ret


;										ESP+4						ESP+8
; It accepts 2 parameters an void *next_thread_registers,void **next_thread_stack
restore_context_asm:
	; EBP restore ederken hata var !!!! DIKKAT

	push ebp
	mov ebp,esp

	;[eb+4] is eip
	;[ebp+8] is next one's registers start address
	;[ebp+12] is next one's active stack


	;eax points to adress of registers
	mov eax, DWORD [ebp+8] ;eax is next's registers

	;restore FS
	;mov	edx,DWORD [eax+28]
	;mov	fs,dx

	;restore ESP
	;edx is the adress of netx's stack
	mov edx, DWORD [ebp+12] ;edx is next's active stack adress
	pop ebp
	mov esp,DWORD [edx]
	;at that point fetch the next's EIP and push it onto stack
	mov edx,DWORD [eax]
	;push edx
	mov [esp],edx

	;restore EBX
	mov ebx,DWORD [eax+4]
	;restore ESI
	mov esi,DWORD [eax+8]
	;restore EDI
	mov edi,DWORD [eax+12]
	;restore ECX
	mov ecx,DWORD [eax+16]
	;restore EDX
	mov edx,DWORD [eax+20]
	;restore EBP
	mov ebp,DWORD [eax+24]

	xor eax,eax
	nop

	;Go back to function that called you
	ret

;										ESP+4						ESP+8
; It accepts 4 parameters an void *next_thread_registers,void **next_thread_stack
;										ESP+12						ESP+16
;							 void *curr_thread_registers, void **curr_thread_stack

switch_asm:
	nop

	;store current stack pointer into active memory of current thread
	mov eax, DWORD [esp+12] ;esp+16 is the adress of the prev thread stack !
	;first save edx here !

	;save EDX
	mov [eax+20],edx
	;save ECX
	mov [eax+16],ecx
	;save EBX
	mov [eax+4],ebx
	;save ESI
	mov [eax+8],esi
	;save EDI
	mov [eax+12],edi
	;save EBP
	mov [eax+24],ebp
	;save FS
	xor	edx, edx
	mov	dx,fs
	mov	[eax+28],edx

	;You can do all you want with registers
	;Now what you need to do is save EIP and save ESP

	;first save the current resigters into current thread's memory
	;save EIP
	mov edx, DWORD [esp]
	mov [eax],edx

	;At that stage we need 2 registers to hold
	;other 2 adresses on the stack
	mov ecx,[esp+4] ;ECX is next registers
	mov ebp,[esp+8] ;EBP is the next stack

	;save esp now
	mov eax,[esp+16]
	pop edx ;CAUTION HERE !!!
	mov [eax],esp	;store the old stack into memory


	;---------------------------------------------------------------------------------------------------------------
	;										RESTORE PART
	;---------------------------------------------------------------------------------------------------------------
	;At that stage we are done with current thread now it is time
	;to restore values from other thread (next one)!

	mov eax,ebp
	; ECX is EIP
	; EAX is ESP

	;restore FS
	mov	edx,DWORD [ecx+28]
	mov	fs,dx

	;restore ESP
	;edx is the adress of netx's stack
	mov esp,DWORD [eax]
	;at that point fetch the next's EIP and push it onto stack
	mov edx,DWORD [ecx]
	push edx
	
	;restore EBX
	mov ebx,DWORD [ecx+4]
	;restore ESI
	mov esi,DWORD [ecx+8]
	;restore EDI
	mov edi,DWORD [ecx+12]
	;restore EDX
	mov edx,DWORD [ecx+20]
	;restore EBP
	mov ebp,DWORD [ecx+24]

	;restore ECX
	mov ecx,DWORD [ecx+16]

	xor eax,eax
	nop
	
	;Go back to function that called you
	ret

	
load_registers_asm:
	nop

	push ebp
	mov ebp,esp

	;function arguments that were passed !
	;[ebp+4] is eip
	;[ebp+8] is the adress of the new fibthread's registers
	mov eax,DWORD [ebp+8]

	;we dont save EIP

	;save EBX
	mov [eax+4],ebx
	;save ESI
	mov [eax+8],esi
	;save EDI
	mov [eax+12],edi
	;save ECX
	mov [eax+16],ecx
	;save EDX
	mov [eax+20],edx
	;save EBP
	pop ebp
	mov [eax+24],ebp

	;save FS
	push edx
	xor	edx, edx
	mov	dx,fs
	mov	[eax+28],edx
	pop edx


	xor eax,eax
	nop

	;Go back to function that called you
	ret
